package eg.edu.eelu.fyp2013.jdetector.core.filters.impl;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.image.BufferedImage;
import eg.edu.eelu.fyp2013.jdetector.core.filters.WholeImageFilter;

public class HistogramEqualization implements WholeImageFilter {
	Dimension imageSize;
	/**
	 * array of rgb integers to cache the input image
	 */
	int[] linearRGBInputImageValues;
	/**
	 */
	int[] linearRGBOutputImageValues;
	/**
	 * 
	 */
	float[][] linearHsbInputImage;
	/**
	 */
	private int[] histogramBeforeEqualization;
	private int[] histogramAfterEqualization;
	/** contains brightness values only.
	 * */
	float[] lookupTableAfterEqualization;

	@Override
	public Image applyFilter(BufferedImage inImage) {
		imageSize = new Dimension(inImage.getWidth(), inImage.getHeight());
		
		//convert image to RGB (fill array of integer)
		linearRGBInputImageValues = inImage.getRGB(0, 0, imageSize.width, imageSize.height, null, 0, imageSize.width);

		//convert RGB to HSB
		linearHsbInputImage = new float[linearRGBInputImageValues.length][] ;
		for (int i = 0; i < linearRGBInputImageValues.length; i++) {
			int rgb = linearRGBInputImageValues[i];
			linearHsbInputImage[i] = Color.RGBtoHSB(0xFF&(rgb>>16), 0xFF&(rgb>>8),0xFF&(rgb), null);
		}
		
		//populate the input histogram
		histogramBeforeEqualization = new int [256];
		histogramAfterEqualization = new int [256];
		lookupTableAfterEqualization = new float [256];
		for (int i = 0; i < linearHsbInputImage.length; i++) {
			//increment the bin corresponding to the pixel brightness
			++histogramBeforeEqualization[(int)(linearHsbInputImage[i][2]*255)];
		}

		//equalize histogram
		//populate cumulative histogram
		int [] cumulativeHistogram = new int[256];
		
		cumulativeHistogram[0]= histogramBeforeEqualization[0];
		for (int i = 1; i < cumulativeHistogram.length; i++) {
			cumulativeHistogram[i]= cumulativeHistogram[i-1]+histogramBeforeEqualization[i];
		}
		for (int i = 0; i < cumulativeHistogram.length; i++) {
			lookupTableAfterEqualization[i] =((float)cumulativeHistogram[i]) / linearRGBInputImageValues.length;
		}
		
		//TODO please revise this for loop
		for (int i = 0; i < histogramBeforeEqualization.length; i++) {
			//old value is i
			int oldFreq = histogramBeforeEqualization[i];
			int newValue = Math.round(lookupTableAfterEqualization[i]*255);
			histogramAfterEqualization[newValue] += oldFreq;
		}
		
		linearRGBOutputImageValues=new int[linearRGBInputImageValues.length];
		for (int i = 0; i < linearRGBOutputImageValues.length; i++) {
			float[] hsb = linearHsbInputImage[i];
			float newBrightness = lookupTableAfterEqualization[Math.round((hsb[2]*255))];
			linearRGBOutputImageValues[i] = Color.HSBtoRGB(hsb[0], hsb[1],newBrightness);
		}
		
		//revert RGB from HSB
		BufferedImage outputImage = new BufferedImage(imageSize.width, imageSize.height, BufferedImage.TYPE_INT_RGB);
		
		outputImage.setRGB(0, 0, imageSize.width, imageSize.height, linearRGBOutputImageValues, 0, imageSize.width);
		return outputImage;
//			form return image
//			return new image

		
		
		
	}


	public int[] getHistogramBeforeEqualization() {
		return histogramBeforeEqualization;
	}


	public int[] getHistogramAfterEqualization() {
		return histogramAfterEqualization;
	}
	

	 
}
